/* test_sha256.c
**
** Copyright (c) 2007, Meadhbh S. Hamrick
** All rights reserved.
** 
** Redistribution  and  use  in  source  and  binary  forms,  with  or  without
** modification, are permitted provided that the following conditions are met:
** 
**  * Redistributions of  source code must  retain the above  copyright notice,
**    this list of conditions and the following disclaimer.
** 
**  * Redistributions in binary form must reproduce the above copyright notice,
**    this list of conditions and the following disclaimer in the documentation
**    and/or other materials provided with the distribution.
** 
**  * Neither the  name of  Project Meadhbh  nor the names of  its contributors
**    may be used  to endorse  or promote  products derived from this  software
**    without specific prior written permission.
** 
** THIS SOFTWARE IS PROVIDED BY  THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY  EXPRESS OR IMPLIED WARRANTIES,  INCLUDING, BUT NOT  LIMITED TO, THE
** IMPLIED WARRANTIES  OF MERCHANTABILITY AND FITNESS FOR  A PARTICULAR PURPOSE
** ARE DISCLAIMED.  IN NO  EVENT SHALL THE  COPYRIGHT OWNER OR  CONTRIBUTORS BE
** LIABLE  FOR  ANY  DIRECT,   INDIRECT,  INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR
** CONSEQUENTIAL  DAMAGES  (INCLUDING,  BUT  NOT  LIMITED  TO,  PROCUREMENT  OF
** SUBSTITUTE GOODS  OR SERVICES;  LOSS OF USE,  DATA, OR PROFITS;  OR BUSINESS
** INTERRUPTION)  HOWEVER CAUSED  AND ON  ANY THEORY  OF LIABILITY,  WHETHER IN
** CONTRACT,  STRICT LIABILITY,  OR  TORT (INCLUDING  NEGLIGENCE OR  OTHERWISE)
** ARISING IN ANY WAY  OUT OF THE USE OF THIS SOFTWARE,  EVEN IF ADVISED OF THE
** POSSIBILITY OF SUCH DAMAGE.
** 
** $Id: test_sha256.c 53 2007-09-01 07:48:29Z msh.mobile $
*/

/** \file test_sha256.c
**  \brief Test SHA256 Cryptographic Hash Functions
**
** This   file   implements   the    tests   that   are   referenced   in
** test_crypto.c.   It  is  assumed   that  the   initalization  function
** suite_sha256_init()   will  be   called  before   any  of   the  test_*()
** functions. The initialization function does all the "heavy lifting" of
** creating  contexts  and hashing  test  vectors.  The individual  tests
** simply  compare output and  intermediate values  with known  good test
** values.
** 
** "Canonical"  test  vectors are  provided  in  the  inputs and  outputs
** arrays.   The inputs array  is an  array of  known strings  that, when
** hashed, are supposed to generate known values.  We're using the values
** from FIPS 180-2,  it's as close to authoratative as  we could find. To
** test the hashing functions, the suite_sha256_init() function hashes each
** string in the inputs array and places the result in the actual_outputs
** array.  In the  test_sha256_fips_vectors() function,  we  simply compare
** what  we generated  in the  actual_outputs array  with the  known good
** values in the outputs array.
** 
** Numerous  tests for cloning  behavior are  performed. Cloning  is used
** extensively in  these tests.  If it doesn't  work, then  it's unlikely
** that anything  will work. But we perform  a number of tests  to see if
** there are particular problems with cloning before or after various sha256
** function calls.
** 
** We test the mc_mic_sha256_clear() function by clearing a used context and
** then  comparing it  with a  newly initialized  context. Note  that the
** clear function  simply reinitializes a  context to it's  default state
** rather than zeroing memory.
** 
** The  mc_mic_sha256_initialize() function is  tested with  the known-value
** checks mentioned above. We also  verify that memory is properly zeroed
** out.
** 
** Finally,  the mc_mic_sha256_update()  function  is tested  by looking  at
** intermediate and final results in sha256 contexts.
*/

/* Macro Definitions */
#define MC_MIC_SHA256_TEST_MAX_CONTEXTS 11
#define MC_MIC_SHA256_TEST_MAX_VECTORS 3

/* File Includes */
#include <string.h>
#include "mutil.h"
#include "mcrypto/sha256.h"
#include "test_sha256.h"
#include <CUnit/CUnit.h>
#include <stdlib.h>
#include <stdio.h>

/* Typedefs, Structs, Unions, Enums, etc. */

/* Static Function Prototypes */

/* Variable Declarations */
tMCSha256 sha256_actual_contexts [ MC_MIC_SHA256_TEST_MAX_CONTEXTS ];
tMCSha256 sha256_contexts [ MC_MIC_SHA256_TEST_MAX_CONTEXTS ] = {
{
  .count = 0x0000000000000000LL,
  .data.asLongLong = {
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL
  },
  .state = {
    0x6A09E667,
    0xBB67AE85,
    0x3C6EF372,
    0xA54FF53A,
    0x510E527F,
    0x9B05688C,
    0x1F83D9AB,
    0x5BE0CD19
  }
},
{
  .count = 0x0000000000000000LL,
  .data.asLongLong = {
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL
  },
  .state = {
    0x6A09E667,
    0xBB67AE85,
    0x3C6EF372,
    0xA54FF53A,
    0x510E527F,
    0x9B05688C,
    0x1F83D9AB,
    0x5BE0CD19
  }
},
{
  .count = 0x0000000000000003LL,
  .data.asLongLong = {
    0x6162630000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL
  },
  .state = {
    0x6A09E667,
    0xBB67AE85,
    0x3C6EF372,
    0xA54FF53A,
    0x510E527F,
    0x9B05688C,
    0x1F83D9AB,
    0x5BE0CD19
  }
},
{
  .count = 0x0000000000000003LL,
  .data.asLongLong = {
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL
  },
  .state = {
    0xBA7816BF,
    0x8F01CFEA,
    0x414140DE,
    0x5DAE2223,
    0xB00361A3,
    0x96177A9C,
    0xB410FF61,
    0xF20015AD
  }
},
{
  .count = 0x0000000000000038LL,
  .data.asLongLong = {
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL
  },
  .state = {
    0x248D6A61,
    0xD20638B8,
    0xE5C02693,
    0x0C3E6039,
    0xA33CE459,
    0x64FF2167,
    0xF6ECEDD4,
    0x19DB06C1
  }
},
{
  .count = 0x0000000000000010LL,
  .data.asLongLong = {
    0x6162636462636465LL,
    0x6364656664656667LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL
  },
  .state = {
    0x6A09E667,
    0xBB67AE85,
    0x3C6EF372,
    0xA54FF53A,
    0x510E527F,
    0x9B05688C,
    0x1F83D9AB,
    0x5BE0CD19
  }
},
{
  .count = 0x0000000000000038LL,
  .data.asLongLong = {
    0x6162636462636465LL,
    0x6364656664656667LL,
    0x6566676866676869LL,
    0x6768696A68696A6BLL,
    0x696A6B6C6A6B6C6DLL,
    0x6B6C6D6E6C6D6E6FLL,
    0x6D6E6F706E6F7071LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL
  },
  .state = {
    0x6A09E667,
    0xBB67AE85,
    0x3C6EF372,
    0xA54FF53A,
    0x510E527F,
    0x9B05688C,
    0x1F83D9AB,
    0x5BE0CD19
  }
},
{
  .count = 0x0000000000000038LL,
  .data.asLongLong = {
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL
  },
  .state = {
    0x248D6A61,
    0xD20638B8,
    0xE5C02693,
    0x0C3E6039,
    0xA33CE459,
    0x64FF2167,
    0xF6ECEDD4,
    0x19DB06C1
  }
},
{
  .count = 0x0000000000000000LL,
  .data.asLongLong = {
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL
  },
  .state = {
    0x6A09E667,
    0xBB67AE85,
    0x3C6EF372,
    0xA54FF53A,
    0x510E527F,
    0x9B05688C,
    0x1F83D9AB,
    0x5BE0CD19
  }
},
{
  .count = 0x0000000000000000LL,
  .data.asLongLong = {
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL
  },
  .state = {
    0x6A09E667,
    0xBB67AE85,
    0x3C6EF372,
    0xA54FF53A,
    0x510E527F,
    0x9B05688C,
    0x1F83D9AB,
    0x5BE0CD19
  }
},
{
  .count = 0x0000000000000010LL,
  .data.asLongLong = {
    0x6162636462636465LL,
    0x6364656664656667LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL,
    0x0000000000000000LL
  },
  .state = {
    0x6A09E667,
    0xBB67AE85,
    0x3C6EF372,
    0xA54FF53A,
    0x510E527F,
    0x9B05688C,
    0x1F83D9AB,
    0x5BE0CD19
  }
}
};

uint8_t *sha256_inputs [ MC_MIC_SHA256_TEST_MAX_VECTORS ] = {
  (uint8_t *) "abc",
  (uint8_t *) "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
  (uint8_t *) "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
};

uint8_t sha256_actual_outputs [ MC_MIC_SHA256_TEST_MAX_VECTORS ][32];

uint8_t sha256_outputs [ MC_MIC_SHA256_TEST_MAX_VECTORS ][32] = {
    { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD },
    { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 },
    { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92, 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67, 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 }
};

/* Function Definitions */

/** \fn int suite_sha256_init( void )
**  \brief Calls various sha256 functions in preparation for value checking.
**  \returns 0 (success)
** 
** This is  the function where "rubber  meets the road." We  call all the
** functions  under test  in this  initialization function  and  in later
** tests simply compare the values we get with known good values.
** 
** We have  a series of tMCSha256  data structures used to  hold the hashing
** context after  various operations. This function  generally performs a
** function,  then clones  the context.  We do  this to  save information
** about the intermediate state of the hash functions. This can help with
** debugging if something  goes wrong. IT IS NOT  THE GENERAL PATTERN FOR
** USING THIS API.
** 
** The algorithm-specific  functions don't  return error codes  and don't
** check parameters. Ergo, we won't  know if there's a failure during the
** init routine's run. We get that info later in the test_*()
** functions.
*/

int suite_sha256_init() {
  uint32_t i;

  /* Initialize the first context */
  mc_mic_sha256_initialize( & (sha256_actual_contexts[0]) );

  /* Clone a context that has not been used */
  mc_mic_sha256_clone( & (sha256_actual_contexts[1]), & (sha256_actual_contexts[0]) ); 

  /* Clone a context for vector 0 */
  mc_mic_sha256_clone( & (sha256_actual_contexts[2]), & (sha256_actual_contexts[0]) );

  /* Hash "abc" (vector 0) */
  mc_mic_sha256_update( & (sha256_actual_contexts[2]), (uint8_t *) sha256_inputs[ 0 ], (uint32_t) strlen( (const char *) sha256_inputs[ 0 ] ) );

  /* Clone this context */
  mc_mic_sha256_clone( & (sha256_actual_contexts[3]), & (sha256_actual_contexts[2]) );

  /* Produce Digest for vector 0 */
  mc_mic_sha256_digest( & (sha256_actual_contexts[3]), (uint8_t *) sha256_actual_outputs[0] );

  /* Clone a context for vector 1 */
  mc_mic_sha256_clone( & (sha256_actual_contexts[4]), & (sha256_actual_contexts[0]) );

  /* Hash 16 bytes of "abcdefghijklmnopqrstuvwxyz" (vector 4) */
  mc_mic_sha256_update( & (sha256_actual_contexts[4]), (uint8_t *) sha256_inputs[1], 16 );

  /* Clone a context that has been updated with exactly 16 bytes, but not
     finalized */
  mc_mic_sha256_clone( & (sha256_actual_contexts[5]), & (sha256_actual_contexts[4]) );

  /* Clone it again so we have something to use */

  mc_mic_sha256_clone( & (sha256_actual_contexts[10]), & (sha256_actual_contexts[4]) );
  /* Hash the remainder of vector 1 */
  mc_mic_sha256_update( & (sha256_actual_contexts[4]), (uint8_t *) & (sha256_inputs[1][16]), (uint32_t) strlen( (const char *) &( sha256_inputs[1][16] ) ) );

  /* Clone a context that has been updated twice, but not finalized */
  mc_mic_sha256_clone( & (sha256_actual_contexts[6]), & (sha256_actual_contexts[4]) );

  /* Produce digest for vector 1 */
  mc_mic_sha256_digest( & (sha256_actual_contexts[4]), (uint8_t *) sha256_actual_outputs[1] );

  /* Clone a context that has been finalized */
  mc_mic_sha256_clone( & (sha256_actual_contexts[7]), & (sha256_actual_contexts[4]) );

  /* Clone a context for vector 2 */
  mc_mic_sha256_clone( & (sha256_actual_contexts[8]), & (sha256_actual_contexts[0]) );

  /* Hash one million "a" characters */
  for( i = 0; i < 10000; i++ ) {
    mc_mic_sha256_update( & (sha256_actual_contexts[8]), (uint8_t *) sha256_inputs[2], (uint32_t) strlen( (const char *) sha256_inputs[2] ) );
  }

  /* Produce digest for vector 2 */
  mc_mic_sha256_digest( & (sha256_actual_contexts[8]), (uint8_t *) sha256_actual_outputs[2] );

  /* Clear context 8 */
  mc_mic_sha256_clear( & (sha256_actual_contexts[8]) );

  /* Clone a context that's been cleared */
  mc_mic_sha256_clone( & (sha256_actual_contexts[9]), &(sha256_actual_contexts[8]) );

  return( 0 );
}

/** \fn void test_sha256_fips_vectors( void )
**  \brief Tests for compatibility with test vectors provided in FIPS 180-2
** 
** During the init function's run, we hashed a number of "canonical" test
** vectors listed in FIPS 180-2.  In this function, we simply compare the
** results  of our  computation (in  the actual_outputs  array)  with the
** known-good values given in the FIPS document (in the outputs array).
*/

void test_sha256_fips_vectors( ) {

  CU_ASSERT_EQUAL( 0, memcmp( sha256_outputs[0], sha256_actual_outputs[0], 32 ) );
  CU_ASSERT_EQUAL( 0, memcmp( sha256_outputs[1], sha256_actual_outputs[1], 32 ) );
  CU_ASSERT_EQUAL( 0, memcmp( sha256_outputs[2], sha256_actual_outputs[2], 32 ) );
}

/** \fn void test_mc_mic_sha256_clone( void )
**  \brief Tests our ability to clone hash contexts
** 
** In this  test, we  look to  see if our  ability to  copy a  context is
** dependent on  the state of the  context. I would be  very surprised if
** this fails.
*/

void test_mc_mic_sha256_clone( ) {
  /* Can we clone a newly initialized context? */
  CU_ASSERT_EQUAL( 0, memcmp( & (sha256_actual_contexts[0]), & (sha256_actual_contexts[1]), sizeof( tMCSha256 ) ) );

  /* Can we clone a context that's been updated with less than one block? */
  CU_ASSERT_EQUAL( 0, memcmp( & (sha256_actual_contexts[10]), & (sha256_actual_contexts[5]), sizeof( tMCSha256 ) ) );
  
  /* Can we clone a context that's been finalized? */
  CU_ASSERT_EQUAL( 0, memcmp( & (sha256_actual_contexts[4]), & (sha256_actual_contexts[7]), sizeof( tMCSha256 ) ) );

  /* Can we clone a context that's been cleared? */
  CU_ASSERT_EQUAL( 0, memcmp( & (sha256_actual_contexts[8]), & (sha256_actual_contexts[9]), sizeof( tMCSha256 ) ) );
}

/** \fn void test_mc_mic_sha256_clear( void )
**  \brief Tests to ensure that sensitive data is cleared
** 
** We test  the mc_mic_sha256_clear() function  by comparing the state  of a
** SHA256 context  after a  call to mc_mic_sha256_clear()  with the state  of a
** context  after a  call to  mc_mic_sha256_initialize(). If  they're equal,
** then we're good.
*/

void test_mc_mic_sha256_clear( ) {
  /* Compare context 0 (newly initialized) with context 8 (newly cleared) */
  CU_ASSERT_EQUAL( 0, memcmp( & (sha256_actual_contexts[0]), & (sha256_actual_contexts[8]), sizeof( tMCSha256 ) ) );
}

/** \fn void test_mc_mic_sha256_initialize( void )
**  \brief Tests the ability to initiailze a newly allocated hashing context. 
*/

void test_mc_mic_sha256_initialize( ) {
  /* Count should be zero */
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].count );

  /* Data values should be zero */
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[ 0] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[ 1] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[ 2] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[ 3] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[ 4] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[ 5] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[ 6] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[ 7] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[ 8] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[ 9] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[10] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[11] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[12] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[13] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[14] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[15] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[16] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[17] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[18] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[19] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[20] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[21] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[22] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[23] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[24] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[25] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[26] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[27] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[28] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[29] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[30] );
  CU_ASSERT_EQUAL( 0LL, sha256_actual_contexts[0].data.asLongLong[31] );

  /* State values are well known */
  CU_ASSERT_EQUAL( 0x6A09E667, sha256_actual_contexts[0].state[0] );
  CU_ASSERT_EQUAL( 0xBB67AE85, sha256_actual_contexts[0].state[1] );
  CU_ASSERT_EQUAL( 0x3C6EF372, sha256_actual_contexts[0].state[2] );
  CU_ASSERT_EQUAL( 0xA54FF53A, sha256_actual_contexts[0].state[3] );
  CU_ASSERT_EQUAL( 0x510E527F, sha256_actual_contexts[0].state[4] );
  CU_ASSERT_EQUAL( 0x9B05688C, sha256_actual_contexts[0].state[5] );
  CU_ASSERT_EQUAL( 0x1F83D9AB, sha256_actual_contexts[0].state[6] );
  CU_ASSERT_EQUAL( 0x5BE0CD19, sha256_actual_contexts[0].state[7] );
}

/** \fn void test_mc_mic_sha256_update( void )
**  \brief Tests the hash update function
** 
** Testing  the update  function is  fairly straight-forward.  We  have a
** series  of  known-good values  for  SHA256  contexts  at different  times
** throught the hashing  process. We simply compare the  test states with
** the known good values.
*/

void test_mc_mic_sha256_update( ) {

#ifndef WORDS_BIGENDIAN
  uint32_t j;

  for( j = 0; j < 8; j++ ) {
    sha256_actual_contexts[3].state[j] = MU_END32( sha256_actual_contexts[3].state[j] );
    sha256_actual_contexts[4].state[j] = MU_END32( sha256_actual_contexts[4].state[j] );
    sha256_actual_contexts[7].state[j] = MU_END32( sha256_actual_contexts[7].state[j] );
  }

  for( j = 0; j < 32; j++ ) {
    sha256_actual_contexts[2].data.asLongLong[j] = MU_END64( sha256_actual_contexts[2].data.asLongLong[j] );
    sha256_actual_contexts[5].data.asLongLong[j] = MU_END64( sha256_actual_contexts[5].data.asLongLong[j] );
    sha256_actual_contexts[6].data.asLongLong[j] = MU_END64( sha256_actual_contexts[6].data.asLongLong[j] );
    sha256_actual_contexts[10].data.asLongLong[j] = MU_END64( sha256_actual_contexts[10].data.asLongLong[j] );
  }
#endif

  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( sha256_actual_contexts[0] ), (uint8_t *) &( sha256_contexts[0] ), sizeof( tMCSha256 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( sha256_actual_contexts[1] ), (uint8_t *) &( sha256_contexts[1] ), sizeof( tMCSha256 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( sha256_actual_contexts[2] ), (uint8_t *) &( sha256_contexts[2] ), sizeof( tMCSha256 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( sha256_actual_contexts[3] ), (uint8_t *) &( sha256_contexts[3] ), sizeof( tMCSha256 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( sha256_actual_contexts[4] ), (uint8_t *) &( sha256_contexts[4] ), sizeof( tMCSha256 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( sha256_actual_contexts[5] ), (uint8_t *) &( sha256_contexts[5] ), sizeof( tMCSha256 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( sha256_actual_contexts[6] ), (uint8_t *) &( sha256_contexts[6] ), sizeof( tMCSha256 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( sha256_actual_contexts[7] ), (uint8_t *) &( sha256_contexts[7] ), sizeof( tMCSha256 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( sha256_actual_contexts[8] ), (uint8_t *) &( sha256_contexts[8] ), sizeof( tMCSha256 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( sha256_actual_contexts[9] ), (uint8_t *) &( sha256_contexts[9] ), sizeof( tMCSha256 ) ) );
  CU_ASSERT_EQUAL( 0, memcmp( (uint8_t *) &( sha256_actual_contexts[10] ), (uint8_t *) &( sha256_contexts[10] ), sizeof( tMCSha256 ) ) );
}

